package dataImport.action.abstracts;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import dataImport.action.manager.EntityReaderManager;
import dataImport.exception.DuplicateAttributeException;
import dataImport.exception.EntityNotFoundException;
import dataImport.exception.MissingAttributeException;
import dataImport.exception.MissingReader;
import dataImport.model.abstracts.AbstractEntity;


public abstract class AbstractEntityReader implements Serializable {

	private static final long serialVersionUID = 8844758146936523301L;

	protected static final String ATTRIBUTE_ID = "id";

	protected HashMap<String, AbstractEntity> abstractEntities;

	private EntityReaderManager entityReaderManager;

	protected abstract AbstractEntity createEntity(final Element element) throws MissingReader;

	public abstract void read(final Document document);

	protected AbstractEntityReader(final EntityReaderManager entityReaderManager) {
		this.abstractEntities = new HashMap<String, AbstractEntity>();
		this.entityReaderManager = entityReaderManager;
	}

	protected final void addEntity(final AbstractEntity abstractEntity) {
		this.abstractEntities.put(abstractEntity.getId(), abstractEntity);
	}

	public final boolean containsEntityWithId(final String id) {
		return this.abstractEntities.containsKey(id);
	}

	public final AbstractEntity getEntityWithId(final String id) throws EntityNotFoundException {
		if (this.abstractEntities.containsKey(id)) {
			return this.abstractEntities.get(id);
		}

		throw new EntityNotFoundException();
	}

	protected final void read(final String entityName, final Document document) {
		final NodeList nodeList = document.getElementsByTagName(entityName);

		for (int i = 0; i < nodeList.getLength(); i++) {
			final Element element = (Element) nodeList.item(i);

			this.addEntity(this.createEntity(element));
		}
	}

	protected final void verifyRestrictions(final String id) {
		if (id.isEmpty()) {
			throw new MissingAttributeException(ATTRIBUTE_ID);
		}

		if (this.containsEntityWithId(id)) {
			throw new DuplicateAttributeException(ATTRIBUTE_ID, id);
		}
	}

	public Collection<AbstractEntity> getAbstractEntities() {
		return this.abstractEntities.values();
	}

	protected EntityReaderManager getEntityReaderManager() {
		return this.entityReaderManager;
	}
}
